﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ebc.componentbinder.Contract;

namespace ebc.componentbinder
{
    partial class ComponentBinder
    {
        internal static IEnumerable<OutputInputPinPair> PairUpPins(IEnumerable<object> components)
        {
            var allOutputPins = from c in components
                                from p in CompileEventsPublishedBy(c)
                                select p;

            var allInputPins = from c in components
                               from p in CompileEventHandlersPublishedBy(c)
                               select p;

            foreach (var pOut in allOutputPins)
            {
                var matchingInputPins = from pIn in allInputPins
                                        where CheckIfPinsMatch(pIn, pOut)
                                        select pIn;

                foreach (var pInMatch in matchingInputPins)
                    yield return new OutputInputPinPair { Out = pOut, In = pInMatch };
            }
        }


        private static bool CheckIfPinsMatch(InputPin pIn, OutputPin pOut)
        {
            return pIn.ParameterType == pOut.ParameterType &&
                   pIn.PinName == pOut.PinName;
        }


        internal static void WireUpPins(OutputInputPinPair pair, Action<object> listener)
        {
            Delegate inputProcessor = pair.In.CreateDelegate();

            if (listener == null)
                pair.Out.AddEventHandler(inputProcessor);
            else
                pair.Out.AddEventHandler(Injector.Intercept(inputProcessor)
                                                 .WithListener(listener));
        }
    }
}
